package com.hunan.api.catv.service.biz.member.sign;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hunan.api.catv.common.CacheName;
import com.hunan.api.catv.entity.ServiceResult;
import com.hunan.api.catv.entity.dto.NewYearLotteryDTO;
import com.hunan.api.catv.entity.po.MemberAssetsDetail;
import com.hunan.api.catv.entity.po.MemberShareRecord;
import com.hunan.api.catv.entity.po.MemberSigninRecord;
import com.hunan.api.catv.entity.vo.MemberSigninRecordVo;
import com.hunan.api.catv.entity.vo.MemberVo;
import com.hunan.api.catv.mq.MqConstants;
import com.hunan.api.catv.service.ResultService;
import com.hunan.api.catv.service.biz.interactive.InteractiveBiz;
import com.hunan.api.catv.service.biz.mq.MqBiz;
import com.hunan.api.catv.service.biz.system.SystemDictBiz;
import com.hunan.api.catv.service.impl.member.MemberService;
import com.hunan.api.catv.utils.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.time.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author jiang zhuan
 * @version 1.0
 * @description 描述
 * @date 2020/11/18 0018
 * @package com.hunan.api.catv.service.biz.member
 * @company 湖南有线
 */
@Service
@CacheConfig(cacheNames = CacheName.signin)
public class MemberSigninRecordBiz extends ResultService {


    private static final Integer LOGIN_ADD_GOLD_TYPE = 1;
    private static final Integer INVITE_ADD_GOLD_TYPE = 3;
    private static final String NEW_YEAR_LOTTERY_CONF = "new_year_lottery_conf";
    @Autowired
    RedisUtils redisUtils;

    @Autowired
    MqBiz mqBiz;

    @Autowired
    InteractiveBiz interactiveBiz;

    @Autowired
    SystemDictBiz systemDictBiz;

    @Autowired
    MemberService memberService;

    private static final Integer INVITATION_NEW_MEMBER_TYPE = 0;
    private static final Integer NORMAL_SIGN_TYPE = 1;
    private static final Integer INVITER_PLATINUM_ISLAND_TYPE = 2;
    private static final Integer INVITER_PLATINUM_ISLAND_MEMBER_ASSETS_TYPE = 2;
    private static final Integer VISIT_PLATINUM_ISLAND_TYPE = 3;
    private static final Integer VISIT_PLATINUM_ISLAND_MEMBER_ASSETS_TYPE = 3;
    private static final Integer NORMAL_STATUS = 1;
    private static final Integer DISABLED_STATUS = 0;

    public static boolean findExsitPlatinumIslandSignin(Integer memberId) {
        MemberSigninRecord memberSigninRecord = new MemberSigninRecord().selectOne(new QueryWrapper<MemberSigninRecord>().eq(MemberSigninRecord.MEMBER_ID, memberId).eq(MemberSigninRecord.STATUS, NORMAL_STATUS).eq(MemberSigninRecord.SIGN_TYPE, VISIT_PLATINUM_ISLAND_TYPE));
        return memberSigninRecord != null;
    }

    public void add(Integer memberId, String type, String deviceId) {
        MemberSigninRecord memberSigninRecord = new MemberSigninRecord();
        memberSigninRecord.setMemberId(memberId);
        memberSigninRecord.setSignType(Integer.valueOf(type));
        memberSigninRecord.setDeviceNo(deviceId);
        memberSigninRecord.setCreateTime(new Date());
        memberSigninRecord.setUpdateTime(new Date());
        memberSigninRecord.insert();
    }

    public boolean findFirstSign(Integer memberId) {
        return new MemberSigninRecord().selectList(new QueryWrapper<MemberSigninRecord>().eq(MemberSigninRecord.MEMBER_ID, memberId).eq(MemberSigninRecord.SIGN_TYPE, INVITATION_NEW_MEMBER_TYPE)).isEmpty();
    }

    public boolean findFirstDevice(String deviceId) {
        return new MemberSigninRecord().selectList(new QueryWrapper<MemberSigninRecord>().eq(MemberSigninRecord.DEVICE_NO, deviceId).eq(MemberSigninRecord.SIGN_TYPE, INVITATION_NEW_MEMBER_TYPE)).isEmpty();
    }

    @Transactional
    public ServiceResult signin(Integer memberId) {
        NewYearLotteryDTO newYearLottery = null;
        try {
            newYearLottery = JSONUtil.toBean(systemDictBiz.getStringByKey(NEW_YEAR_LOTTERY_CONF), NewYearLotteryDTO.class);
        } catch (Exception e) {
            log.error("获取抽奖时间配置错误", e);
            newYearLottery = new NewYearLotteryDTO();
        }
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime beginTime = newYearLottery.getBeginTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime endTime = newYearLottery.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        if (!(now.isAfter(beginTime) && now.isBefore(endTime))) {
            return buildFail("活动暂未开始");
        }
        LocalDateTime todayStartTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);//当天00:00:00
        LocalDateTime todayEndTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);//当天23:59:59
        MemberSigninRecord existMemberSigninRecord = new MemberSigninRecord().selectOne(new QueryWrapper<MemberSigninRecord>().eq(MemberSigninRecord.MEMBER_ID, memberId).eq(MemberSigninRecord.SIGN_TYPE, NORMAL_SIGN_TYPE).eq(MemberSigninRecord.STATUS, NORMAL_STATUS).between(MemberSigninRecord.CREATE_TIME, todayStartTime, todayEndTime));
        if (existMemberSigninRecord != null) {
            return buildFail(false, "今日已完成签到");
        }
        MemberSigninRecord memberSigninRecord = new MemberSigninRecord();
        memberSigninRecord.setSignType(NORMAL_SIGN_TYPE);
        memberSigninRecord.setCreateTime(new Date());
        memberSigninRecord.setUpdateTime(new Date());
        memberSigninRecord.setMemberId(memberId);
        memberSigninRecord.setStatus(NORMAL_STATUS);
        boolean insert = memberSigninRecord.insert();
        if (insert) {
            mqBiz.push(MqConstants.LOGIN_ADD_LOTTERY_EXCHANGE, MqConstants.LOGIN_ADD_LOTTERY_ROUTINGKEY, memberId);
            redisUtils.delObjectCacheListPattern("signinRecord_" + memberId);
        }
        return buildOK(true, "签到成功");
    }


    public ServiceResult signinRecord(Integer memberId) {
        Map<String, Object> result = (Map<String, Object>) redisUtils.get("signinRecord_" + memberId);
        if (result != null && !result.isEmpty()) {
            return buildOK(result);
        }
        if (memberId == null) {
            return buildOK(false);
        }
        result = new HashMap<>();
        LocalDateTime todayStartTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);//当天00:00:00
        LocalDateTime todayEndTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);//当天23:59:59
        List<MemberSigninRecordVo> memberSigninRecordVos = this.getMemberSigninRecordVos(memberId);
        result.put("recordList", memberSigninRecordVos);
        MemberSigninRecord memberSigninRecord = new MemberSigninRecord().selectOne(new QueryWrapper<MemberSigninRecord>().eq(MemberSigninRecord.MEMBER_ID, memberId).eq(MemberSigninRecord.SIGN_TYPE, NORMAL_SIGN_TYPE).eq(MemberSigninRecord.STATUS, NORMAL_STATUS).between(MemberSigninRecord.CREATE_TIME, todayStartTime, todayEndTime));
        result.put("today", memberSigninRecord != null);
        Duration between = Duration.between(LocalDateTime.now(), todayEndTime);
        redisUtils.set("signinRecord_" + memberId, result, between.getSeconds());
        return buildOK(result);
    }

    public List<MemberSigninRecordVo> getMemberSigninRecordVos(Integer memberId) {
        List<MemberSigninRecord> memberSigninRecords = new MemberSigninRecord().selectList(new QueryWrapper<MemberSigninRecord>().eq(MemberSigninRecord.MEMBER_ID, memberId).eq(MemberSigninRecord.SIGN_TYPE, NORMAL_SIGN_TYPE).eq(MemberSigninRecord.STATUS, NORMAL_STATUS));
        return memberSigninRecords.stream().map(memberSigninRecord -> {
            MemberSigninRecordVo memberSigninRecordVo = new MemberSigninRecordVo();
            BeanUtil.copyProperties(memberSigninRecord, memberSigninRecordVo, true);
            memberSigninRecordVo.setCreateTime(DateUtil.formatDateTime(memberSigninRecord.getCreateTime()));
            memberSigninRecordVo.setUpdateTime(DateUtil.formatDateTime(memberSigninRecord.getUpdateTime()));
            return memberSigninRecordVo;
        }).collect(Collectors.toList());
    }

    public void changePlatinumIslandInviteState(Integer memberId) {
        MemberSigninRecord memberSigninRecord = new MemberSigninRecord().selectOne(new QueryWrapper<MemberSigninRecord>().eq(MemberSigninRecord.SIGN_TYPE, INVITER_PLATINUM_ISLAND_TYPE).eq(MemberSigninRecord.MEMBER_ID, memberId).eq(MemberSigninRecord.STATUS, DISABLED_STATUS));
        if (memberSigninRecord != null) {
            ServiceResult addGoldResult = null;
            try {
                addGoldResult = interactiveBiz.addGoldToByPlatinumIslandTask(INVITE_ADD_GOLD_TYPE, memberSigninRecord.getCreateBy());
            } catch (NoSuchAlgorithmException e) {
                log.error("调用白金岛接口异常", e);
            }
            boolean status = addGoldResult.getStatus();
            if (status) {
                memberSigninRecord.setStatus(NORMAL_STATUS);
                memberSigninRecord.setUpdateTime(new Date());
                memberSigninRecord.setUpdateBy(memberId);
                boolean updateById = memberSigninRecord.updateById();
                if (updateById) {
                    JSONObject data = (JSONObject) addGoldResult.getData();
                    recordInviteAssetsDetail(memberId, memberSigninRecord.getCreateBy(), ((JSONObject) data.get("data")).getString("gold_val"));
                }
            }
        }
    }

    private void recordInviteAssetsDetail(Integer memberId, Integer inviterId, String goldVal) {
        if (StringUtils.isBlank(goldVal)) {
            goldVal = "0";
        }
        MemberAssetsDetail memberAssetsDetail = new MemberAssetsDetail();
        memberAssetsDetail.setCreateTime(new Date());
        memberAssetsDetail.setMemberId(inviterId);
        memberAssetsDetail.setType(INVITER_PLATINUM_ISLAND_MEMBER_ASSETS_TYPE);
        memberAssetsDetail.setVariableAmount("+" + goldVal + "金币");
        memberAssetsDetail.setAmount(new BigDecimal(goldVal));
        memberAssetsDetail.setReason("白金岛助力活动：用户" + memberId + "助力了用户" + inviterId + "，用户" + inviterId + "的白金岛资产增加了" + goldVal + "金币");
        memberAssetsDetail.insert();
    }

    @Transactional
    public ServiceResult visitPlatinumIsland(Integer memberId) {
        boolean isSignin = MemberSigninRecordBiz.findExsitPlatinumIslandSignin(memberId);
        if (!isSignin) {
            ServiceResult addGoldResult = null;
            try {
                addGoldResult = interactiveBiz.addGoldToByPlatinumIslandTask(LOGIN_ADD_GOLD_TYPE, memberId);
            } catch (NoSuchAlgorithmException e) {
                log.error("调用白金岛接口异常", e);
            }
            boolean status = addGoldResult.getStatus();
            if (status) {
                MemberSigninRecord memberSigninRecord = new MemberSigninRecord();
                memberSigninRecord.setUpdateTime(new Date());
                memberSigninRecord.setStatus(NORMAL_STATUS);
                memberSigninRecord.setMemberId(memberId);
                memberSigninRecord.setCreateTime(new Date());
                memberSigninRecord.setSignType(VISIT_PLATINUM_ISLAND_TYPE);
                boolean insert = memberSigninRecord.insert();
                if (insert) {
                    JSONObject data = (JSONObject) addGoldResult.getData();
                    recordVisitAssetsDetail(memberId, ((JSONObject) data.get("data")).getString("gold_val"));
                    return buildOK(true, "登陆获取奖励成功");
                }
                return buildFail("登陆获取奖励失败");
            } else {
                return buildFail(addGoldResult.getMsg());
            }
        }
        return buildFail("已经登陆领取过奖励了，更多精彩请登录蜗牛APP！");
    }

    private void recordVisitAssetsDetail(Integer memberId, String goldVal) {
        if (StringUtils.isBlank(goldVal)) {
            goldVal = "0";
        }
        MemberAssetsDetail memberAssetsDetail = new MemberAssetsDetail();
        memberAssetsDetail.setCreateTime(new Date());
        memberAssetsDetail.setMemberId(memberId);
        memberAssetsDetail.setType(VISIT_PLATINUM_ISLAND_MEMBER_ASSETS_TYPE);
        memberAssetsDetail.setVariableAmount("+" + goldVal + "金币");
        memberAssetsDetail.setAmount(new BigDecimal(goldVal));
        memberAssetsDetail.setReason("白金岛首次登陆活动：用户" + memberId + "首次登陆绑定，用户" + memberId + "的白金岛资产增加了" + goldVal + "金币");
        memberAssetsDetail.insert();
    }

    public ServiceResult getPlatinumIslandInviteList(Integer memberId) {
//        Map<String, Object> result = new HashMap<>();
        List<MemberSigninRecord> memberSigninRecords = new MemberSigninRecord().selectList(new QueryWrapper<MemberSigninRecord>().eq(MemberSigninRecord.SIGN_TYPE, INVITER_PLATINUM_ISLAND_TYPE).eq(MemberSigninRecord.CREATE_BY, memberId));
        List<MemberSigninRecordVo> signinRecordVos = memberSigninRecords.stream().map(memberSigninRecord -> {
            MemberSigninRecordVo memberSigninRecordVo = new MemberSigninRecordVo();
            BeanUtil.copyProperties(memberSigninRecord, memberSigninRecordVo, true);
            MemberVo memberVo = memberService.getById(memberSigninRecord.getMemberId());
//            StrUtil.hide(byId.getPhone(), 3, 7);
            String nickName = memberVo.getNickName();
            if (StringUtils.isNotBlank(nickName)) {
                int length = nickName.length();
                if (length > 1) {
                    nickName = nickName.substring(0, 1) + "**" + nickName.substring(length - 1);
                }
            }
            memberSigninRecordVo.setNickName(nickName);
            memberSigninRecordVo.setAvatarUrl(memberVo.getAvatarUrl());
            return memberSigninRecordVo;
        }).collect(Collectors.toList());
//        long count = memberSigninRecords.stream().filter(memberSigninRecord -> memberSigninRecord.getStatus().equals(NORMAL_STATUS)).count();
//        result.put("overSuccess", count > 15);
//        result.put("list", memberSigninRecords);
        return buildOK(signinRecordVos);
    }

    public ServiceResult addShare(Integer memberId, MemberShareRecord memberShareRecord) {
        memberShareRecord.setId(null);
        memberShareRecord.setDeleted(1);
        memberShareRecord.setCreateTime(new Date());
        memberShareRecord.setMemberId(memberId);
        return buildOK(memberShareRecord.insert());
    }

}
